#!/usr/local/bin/python2.4

# Test the icon module with examples from the Icon programming language book.

import icon
import operator
import sys

def test1():
    int3 = 3
    real4 = 4.0
    apple = "apple"
    primes = [2, 3, 5, 7, 11, 13]
    fruits = ["grape", "apple", "lemon"]
    fractions = (1.5, -0.2, 9.4)

    icon.display(icon.Generator(int3))
    icon.display(icon.Generator(real4))
    icon.display(icon.Generator(apple))
    icon.display(icon.Generator(primes))
    icon.display(icon.Generator(fruits))
    icon.display(icon.Generator(fractions))

    icon.display(icon.apply(lambda x: True, int3))
    icon.display(icon.apply(lambda x: x % 2 == 1, primes))
    icon.display(icon.apply(lambda x: 'a' in x, fruits))

    icon.display(icon.apply(lambda x, y: x * y, primes, fractions))
    
    def cat_less_than(x, y):
        if x < y:
            return str(x) + str(y)
        else:
            raise icon.Failure

    print icon.first_do(cat_less_than, real4, fractions)

    def cat_len_greater_than(x, y):
        if x > len(y):
            return str(x) + y
        else:
            raise icon.Failure

    print icon.first_do(cat_len_greater_than, primes, fruits)


def test2():
    odds = [1, 3, 5]

    icon.display(icon.apply(lambda x, y, z: x * y * z, odds, odds, odds))

    def equality(x, y, z):
        return x == y and y == z

    icon.display(icon.apply(lambda x, y, z: x*x + y*y + z*z,   \
                            odds, odds, odds))

    def polynomial_if_equal(x, y, z):
        if x == y == z:
            return (x + y) * (y + z)
        else:
            raise icon.Failure

    print icon.first_do(polynomial_if_equal, odds, odds, odds)

test1()
test2()

# Examples from section 14.1

# Add two ranges of integers  (1 to 5) + (1 to 3) should produce
# {2, 3, 4, 3, 4, 5, 4, 5, 6, 5, 6, 7, 6, 7, 8}
def add_integer_ranges():
    icon.display(icon.apply(operator.add, xrange(1, 6), xrange(1, 4)))

# Iterate over three strings and concatenate the characters together
# !s1 || !s2 || !s3
def concatenate_strings():
    s1 = "ralph"
    s2 = "dave"
    s3 = "chris"
    icon.display(icon.apply(lambda a, b, c: a + b + c, \
                            list(s1), list(s2), list(s3)))

# Write the octal codes for ASCII characters
def octal_codes():
    def write(a, b, c):
        print "%d%d%d" % (a, b, c)

    icon.every_do(write, xrange(0, 2), xrange(0, 8), xrange(0, 8))

# Select an increasing or decreasing sequence based on the sign of j
def up_or_down(j):
    def p(i):
        print i

    def sequence():
        if j > 0:
            return xrange(1, j+1)
        else:
            return xrange(-1, j-1, -1)

    # Note that we evaluate sequence to form a generator.  It's the lambda 
    # expression we're really evaluating.
    icon.every_do(lambda i: p(i), sequence())

def alternate():
    # Alternate the sequences (1 to 5), (10 to 15) and (20 to 25)
    alts = icon.Generator(xrange(1, 6), xrange(10, 16), xrange(20, 26))
    icon.display(icon.apply(lambda x: x, alts))

    # Generators can be arguments to other Generators
    alts = icon.Generator(icon.Generator(xrange(30, 36)), xrange(40, 46), \
                          icon.Generator(xrange(50, 56)))
    icon.display(icon.apply(lambda x: x, alts))


add_integer_ranges()
concatenate_strings()
octal_codes()
up_or_down(10)
up_or_down(-10)
alternate()

